﻿Imports Kirishima16.Net.Twitter
Imports System.Collections.Specialized
Imports System.Net

Namespace Anis.Net.Twitter
    Public Class TwitterClient
        Implements ITwitterClient

#Region "URL定数"
        Private ReadOnly _urlBlocks As String = "http://twitter.com/blocks/"
        Private ReadOnly _urlFavorites As String = "http://twitter.com/favorites"
        Private ReadOnly _urlFriendships As String = "http://twitter.com/friendships/"
        Private ReadOnly _urlDirectMessages As String = "http://twitter.com/direct_messages"
        Private ReadOnly _urlFavourings As String = "http://twitter.com/favourings"
        Private ReadOnly _urlStatuses As String = "http://twitter.com/statuses"
        Private ReadOnly _urlStatusesFeaturedXml As String = "http://twitter.com/statuses/featured.xml"
        Private ReadOnly _urlStatusesFollowers As String = "http://twitter.com/statuses/followers"
        Private ReadOnly _urlStatusesFriends As String = "http://twitter.com/statuses/friends"
        Private ReadOnly _urlUsers As String = "http://twitter.com/users"
#End Region

        Private _userName As String
        Private _password As String

        ''' <summary>
        ''' TwitterClientがユーザー名とパスワードで初期化されているかを取得します
        ''' </summary>
        ''' <returns>初期化していればTrue,初期化していなければFalse</returns>
        Public ReadOnly Property IsLogined() As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.IsLogined
            Get
                Return Not (String.IsNullOrEmpty(_password) OrElse String.IsNullOrEmpty(_userName))
            End Get
        End Property

        ''' <summary>
        ''' Loginメソッドを実行したときに渡したユーザー名を取得します。
        ''' </summary>
        ''' <returns>ユーザー名</returns>
        Public ReadOnly Property UserName() As String Implements Kirishima16.Net.Twitter.ITwitterClient.UserName
            Get
                Return _userName
            End Get
        End Property

        ''' <summary>
        ''' TwitterClientをユーザー名とパスワードで初期化します
        ''' </summary>
        ''' <param name="userName">ユーザー名</param>
        ''' <param name="password">パスワード</param>
        ''' <returns>常にSuccess</returns>
        Public Function Login(ByVal userName As String, ByVal password As String) As Kirishima16.Net.Twitter.LoginResult Implements Kirishima16.Net.Twitter.ITwitterClient.Login
            Me._userName = userName
            Me._password = password
            Return Kirishima16.Net.Twitter.LoginResult.Success
        End Function

        ''' <summary>
        ''' ユーザー名とパスワードをクリアします
        ''' </summary>
        ''' <returns>常にSuccess</returns>
        Public Function Logout() As Kirishima16.Net.Twitter.LogoutResult Implements Kirishima16.Net.Twitter.ITwitterClient.Logout
            _userName = Nothing
            _password = Nothing
            Return Kirishima16.Net.Twitter.LogoutResult.Success
        End Function

        ''' <summary>
        ''' ステータス文字列を指定して投稿します。
        ''' </summary>
        ''' <param name="status">ステータス文字列</param>
        ''' <returns>投稿されたステータス</returns>
        Public Function UpdateStatus(ByVal status As String) As Kirishima16.Net.Twitter.TwitterStatus Implements Kirishima16.Net.Twitter.ITwitterClient.UpdateStatus
            Return UpdateStatus(status, 0)
        End Function

        ''' <summary>
        ''' ステータス文字列と返信先のステータスを指定して投稿します。
        ''' </summary>
        ''' <param name="status">ステータス文字列</param>
        ''' <param name="inReplyToStatus">返信先のステータス</param>
        ''' <returns>投稿されたステータス</returns>
        Public Function UpdateStatus(ByVal status As String, ByVal inReplyToStatus As Kirishima16.Net.Twitter.TwitterStatus) As Kirishima16.Net.Twitter.TwitterStatus Implements Kirishima16.Net.Twitter.ITwitterClient.UpdateStatus
            Return UpdateStatus(status, inReplyToStatus.StatusID)
        End Function

        ''' <summary>
        ''' ステータス文字列と返信先のステータスIDを指定して投稿します。
        ''' </summary>
        ''' <param name="status">ステータス文字列</param>
        ''' <param name="inReplyToStatusID">返信先のステータスID</param>
        ''' <returns>投稿されたステータス</returns>
        Public Function UpdateStatus(ByVal status As String, ByVal inReplyToStatusID As Long) As Kirishima16.Net.Twitter.TwitterStatus Implements Kirishima16.Net.Twitter.ITwitterClient.UpdateStatus
            Dim nvc As New NameValueCollection()
            If inReplyToStatusID > 0 Then
                nvc.Add("in_reply_to_status_id", inReplyToStatusID.ToString())
            End If
            nvc.Add("status", status)

            Dim webClient As WebClient = Nothing
            Dim url As String = _urlStatuses + "/update.json"
            Dim res As String = webClient.HttpPost(url, nvc, _userName, _password)
            Return Me.CreateTwitterStatus(res)
        End Function

        ''' <summary>
        ''' 投稿したステータスを削除します。
        ''' </summary>
        ''' <param name="statusID">ステータスID</param>
        ''' <returns>削除に成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function DestroyStatus(ByVal statusID As Long) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.DestroyStatus
            Try
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlStatuses + "/destroy/" + statusID.ToString() + ".json"
                webClient.HttpPost(url, New NameValueCollection(), _userName, _password)
            Catch ex As Exception
                Return False
            End Try
            Return True
        End Function

        ''' <summary>
        ''' 指定したステータスをお気に入りに追加します。
        ''' </summary>
        ''' <param name="statusID">ステータスID</param>
        ''' <returns>追加に成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function CreateFavorite(ByVal statusID As Long) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.CreateFavorite
            Try
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlFavorites + "/create/" + statusID.ToString() + ".json"
                webClient.HttpPost(url, New NameValueCollection(), _userName, _password)
            Catch
                Return False
            End Try
            Return True
        End Function

        ''' <summary>
        ''' 指定したステータスをお気に入りから削除します。
        ''' </summary>
        ''' <param name="statusID">ステータスID</param>
        ''' <returns>削除に成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function DestroyFavorite(ByVal statusID As Long) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.DestroyFavorite
            Try
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlFavorites + "/destroy/" + statusID.ToString() + ".json"
                webClient.HttpPost(url, New NameValueCollection(), _userName, _password)
            Catch
                Return False
            End Try
            Return True
        End Function

        ''' <summary>
        ''' すべてのページから自分がフォローしているユーザーのコレクションを取得します。
        ''' </summary>
        ''' <returns>ユーザーのコレクション</returns>
        Public Function GetFriends() As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterUser) Implements Kirishima16.Net.Twitter.ITwitterClient.GetFriends
            Dim page As Integer = 0
            Dim userList As New List(Of TwitterUser)
            Dim tmpUserList As New List(Of TwitterUser)
            Do
                page = page + 1
                tmpUserList.Clear()
                tmpUserList = DirectCast(GetFriends(page, page), List(Of TwitterUser))
                userList.AddRange(tmpUserList)
            Loop While tmpUserList.Count >= 100

            Return userList
        End Function

        ''' <summary>
        ''' ページを指定して自分がフォローしているユーザーのコレクションを取得します。
        ''' </summary>
        ''' <param name="beginPage">取得開始ページ</param>
        ''' <param name="endPage">取得終了ページ</param>
        ''' <returns>ユーザーのコレクション</returns>
        Public Function GetFriends(ByVal beginPage As Integer, ByVal endPage As Integer) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterUser) Implements Kirishima16.Net.Twitter.ITwitterClient.GetFriends
            Dim userList As New List(Of TwitterUser)

            For i As Integer = beginPage To endPage
                Dim values As New NameValueCollection()
                values.Add("page", i.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlStatusesFriends & ".json"
                Dim res As String = webClient.HttpGet(url, values, _userName, _password)
                userList.AddRange(Me.CreateTwitterUsers(res))
            Next

            Return userList
        End Function

        ''' <summary>
        ''' すべてのページから自分をフォローしているユーザーのコレクションを取得します。
        ''' </summary>
        ''' <returns>ユーザーのコレクション</returns>
        Public Function GetFollowers() As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterUser) Implements Kirishima16.Net.Twitter.ITwitterClient.GetFollowers
            Dim page As Integer = 0
            Dim userList As New List(Of TwitterUser)
            Dim tmpUserList As New List(Of TwitterUser)
            Do
                page = page + 1
                tmpUserList.Clear()
                tmpUserList = DirectCast(GetFollowers(page, page), List(Of TwitterUser))
                userList.AddRange(tmpUserList)
            Loop While tmpUserList.Count >= 100
            Return userList
        End Function

        ''' <summary>
        ''' ページを指定して自分をフォローしているユーザーのコレクションを取得します。
        ''' </summary>
        ''' <param name="beginPage">取得開始ページ</param>
        ''' <param name="endPage">取得終了ページ</param>
        ''' <returns>フォローしているユーザーのコレクション</returns>
        Public Function GetFollowers(ByVal beginPage As Integer, ByVal endPage As Integer) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterUser) Implements Kirishima16.Net.Twitter.ITwitterClient.GetFollowers
            Dim userList As New List(Of TwitterUser)

            For i As Integer = beginPage To endPage
                Dim values As New NameValueCollection()
                values.Add("page", i.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlStatusesFollowers & ".json"
                Dim res As String = webClient.HttpGet(url, values, _userName, _password)
                userList.AddRange(Me.CreateTwitterUsers(res))
            Next

            Return userList
        End Function

        ''' <summary>
        ''' TwitterUserを指定してユーザーをフォローします。
        ''' </summary>
        ''' <param name="user">フォローするTwitterUser</param>
        ''' <returns>フォローに成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function CreateFriendship(ByVal user As Kirishima16.Net.Twitter.TwitterUser) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.CreateFriendship
            Return CreateFriendship(user.UserName)
        End Function

        ''' <summary>
        ''' ユーザー名を指定してユーザーをフォローします。
        ''' </summary>
        ''' <param name="userName">フォローするユーザー名</param>
        ''' <returns>フォローに成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function CreateFriendship(ByVal userName As String) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.CreateFriendship
            Try
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlFriendships + "create/" + userName + ".json"
                webClient.HttpPost(url, New NameValueCollection, _userName, _password)
            Catch ex As WebException
                Return False
            End Try
            Return True
        End Function

        ''' <summary>
        ''' TwitterUserを指定してユーザーをフォロー解除します。
        ''' </summary>
        ''' <param name="user">フォロー解除するTwitterUser</param>
        ''' <returns>フォロー解除に成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function DestroyFriendship(ByVal user As Kirishima16.Net.Twitter.TwitterUser) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.DestroyFriendship
            Return DestroyFriendship(user.UserName)
        End Function

        ''' <summary>
        ''' ユーザー名を指定してフォロー解除します。
        ''' </summary>
        ''' <param name="userName">フォロー解除するユーザー名</param>
        ''' <returns>フォロー解除に成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function DestroyFriendship(ByVal userName As String) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.DestroyFriendship
            Try
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlFriendships + "destroy/" + userName + ".json"
                webClient.HttpPost(url, New NameValueCollection(), _userName, _password)
            Catch
                Return False
            End Try
            Return True
        End Function

        ''' <summary>
        ''' TwitterUserを指定してユーザーをブロックします。
        ''' </summary>
        ''' <param name="user">ブロックするTwitterUser</param>
        ''' <returns>ブロックに成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function CreateBlock(ByVal user As TwitterUser) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.CreateBlock
            Return CreateBlock(user.UserName)
        End Function

        ''' <summary>
        ''' ユーザー名を指定してブロックします。
        ''' </summary>
        ''' <param name="userName">ブロックするユーザー名</param>
        ''' <returns>ブロックに成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function CreateBlock(ByVal userName As String) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.CreateBlock
            Try
                Dim values As New NameValueCollection()
                values.Add("id", userName)
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlBlocks + "create/" + userName + ".json"
                webClient.HttpPost(url, values, _userName, _password)
            Catch
                Return False
            End Try
            Return True
        End Function

        ''' <summary>
        ''' TwitterUserを指定してユーザーをブロック解除します。
        ''' </summary>
        ''' <param name="user">ブロック解除するTwitterUser</param>
        ''' <returns>ブロック解除に成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function DestroyBlock(ByVal user As Kirishima16.Net.Twitter.TwitterUser) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.DestroyBlock
            Return DestroyBlock(user.UserName)
        End Function

        ''' <summary>
        ''' ユーザー名を指定してブロック解除します。
        ''' </summary>
        ''' <param name="userName">ブロック解除するユーザー名</param>
        ''' <returns>ブロック解除に成功すればTrue、失敗すればFalse</returns>
        ''' <remarks></remarks>
        Public Function DestroyBlock(ByVal userName As String) As Boolean Implements Kirishima16.Net.Twitter.ITwitterClient.DestroyBlock
            Try
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlBlocks + "destroy/" + userName + ".json"
                webClient.HttpPost(url, New NameValueCollection(), _userName, _password)
            Catch
                Return False
            End Try
            Return True
        End Function

        ''' <summary>
        ''' パブリック(Public)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatus">取得済みの最新のステータス 無視される可能性あり</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        ''' <remarks></remarks>
        Public Function GetPublicTimeline(ByVal maxPage As Integer, ByVal lastStatus As Kirishima16.Net.Twitter.TwitterStatus) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetPublicTimeline
            Return GetPublicTimeline(maxPage, lastStatus.StatusID)
        End Function

        ''' <summary>
        ''' パブリック(Public)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatusID">取得済みの最新のステータスの固有ID　無視される可能性あり</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        ''' <remarks></remarks>
        Public Function GetPublicTimeline(ByVal maxPage As Integer, ByVal lastStatusID As Long) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetPublicTimeline
            Dim statusList As New List(Of TwitterStatus)

            For page As Integer = 1 To maxPage
                Dim options As New NameValueCollection()
                If lastStatusID > 0 Then
                    options.Add("since_id", lastStatusID.ToString())
                End If
                options.Add("page", page.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlStatuses + "/public_timeline.json"
                Dim res As String = webClient.HttpGet(url, options, _userName, _password)
                statusList.AddRange(Me.CreateTwitterStatuses(res))
            Next

            Return statusList
        End Function

        ''' <summary>
        ''' ホーム(Recent/Friends)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatus">取得済みの最新のステータス</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        Public Function GetHomeTimeline(ByVal maxPage As Integer, ByVal lastStatus As Kirishima16.Net.Twitter.TwitterStatus) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetHomeTimeline
            Dim statusID As Long
            If lastStatus Is Nothing Then
                statusID = -1
            Else
                statusID = lastStatus.StatusID
            End If
            Return GetHomeTimeline(maxPage, lastStatus.StatusID)
        End Function

        ''' <summary>
        ''' ホーム(Recent/Friends)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatusID">取得済みの最新のステータスの固有ID 0以下で無視</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        Public Function GetHomeTimeline(ByVal maxPage As Integer, ByVal lastStatusID As Long) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetHomeTimeline
            Dim statusList As New List(Of TwitterStatus)

            For page As Integer = 1 To maxPage
                Dim options As New NameValueCollection()
                If lastStatusID > 0 Then
                    options.Add("since_id", lastStatusID.ToString())
                End If
                options.Add("page", page.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlStatuses + "/friends_timeline.json"
                Dim res As String = webClient.HttpGet(url, options, _userName, _password)
                statusList.AddRange(Me.CreateTwitterStatuses(res))
            Next

            Return statusList
        End Function

        ''' <summary>
        ''' 返信(Replies/Memento)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatus">取得済みの最新のステータス</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        ''' <remarks></remarks>
        Public Function GetRepliesTimeline(ByVal maxPage As Integer, ByVal lastStatus As Kirishima16.Net.Twitter.TwitterStatus) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetRepliesTimeline
            Return GetRepliesTimeline(maxPage, lastStatus.StatusID)
        End Function

        ''' <summary>
        ''' 返信(Replies/Memento)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatusID">取得済みの最新のステータスの固有ID</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        Public Function GetRepliesTimeline(ByVal maxPage As Integer, ByVal lastStatusID As Long) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetRepliesTimeline
            Dim statusList As New List(Of TwitterStatus)

            For page As Integer = 1 To maxPage
                Dim options As New NameValueCollection()
                If lastStatusID > 0 Then
                    options.Add("since_id", lastStatusID.ToString())
                End If
                options.Add("page", page.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlStatuses + "/replies.json"
                Dim res As String = webClient.HttpGet(url, options, _userName, _password)
                statusList.AddRange(Me.CreateTwitterStatuses(res))
            Next

            Return statusList
        End Function

        ''' <summary>
        ''' 受信ダイレクトメッセージ(Inbox)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatus">取得済みの最新のステータス</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        ''' <remarks></remarks>
        Public Function GetInboxTimeline(ByVal maxPage As Integer, ByVal lastStatus As Kirishima16.Net.Twitter.TwitterStatus) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetInboxTimeline
            Return GetInboxTimeline(maxPage, lastStatus.StatusID)
        End Function

        ''' <summary>
        ''' 受信ダイレクトメッセージ(Inbox)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatusID">取得済みの最新のステータスの固有ID</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        Public Function GetInboxTimeline(ByVal maxPage As Integer, ByVal lastStatusID As Long) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetInboxTimeline
            Dim directMessageList As New List(Of TwitterStatus)

            For page As Integer = 1 To maxPage
                Dim options As New NameValueCollection()
                If lastStatusID > 0 Then
                    options.Add("since_id", lastStatusID.ToString())
                End If
                options.Add("page", page.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlDirectMessages + ".json"
                Dim res As String = webClient.HttpGet(url, options, _userName, _password)
                directMessageList.AddRange(Me.CreateTwitterStatuses(res))
            Next

            Return directMessageList
        End Function

        ''' <summary>
        ''' 送信ダイレクトメッセージ(Sent)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatus">取得済みの最新のステータス</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        ''' <remarks></remarks>
        Public Function GetSentTimeline(ByVal maxPage As Integer, ByVal lastStatus As Kirishima16.Net.Twitter.TwitterStatus) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetSentTimeline
            Return GetSentTimeline(maxPage, lastStatus.StatusID)
        End Function

        ''' <summary>
        ''' 送信ダイレクトメッセージ(Sent)タイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatusID">取得済みの最新のステータスの固有ID</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        ''' <remarks></remarks>
        Public Function GetSentTimeline(ByVal maxPage As Integer, ByVal lastStatusID As Long) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetSentTimeline
            Dim directMessageList As New List(Of TwitterStatus)

            For page As Integer = 1 To maxPage
                Dim options As New NameValueCollection()
                If lastStatusID > 0 Then
                    options.Add("since_id", lastStatusID.ToString())
                End If
                options.Add("page", page.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlDirectMessages + "/sent.json"
                Dim res As String = webClient.HttpGet(url, options, _userName, _password)
                directMessageList.AddRange(Me.CreateTwitterStatuses(res))
            Next

            Return directMessageList
        End Function

        ''' <summary>
        ''' ユーザーのタイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatus">取得済みの最新のステータス</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        Public Function GetUserTimeline(ByVal maxPage As Integer, ByVal lastStatus As Kirishima16.Net.Twitter.TwitterStatus, ByVal user As Kirishima16.Net.Twitter.TwitterUser) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetUserTimeline
            Return GetUserTimeline(maxPage, lastStatus.StatusID, user.UserName)
        End Function

        ''' <summary>
        ''' ユーザーのタイムラインを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatusID">取得済みの最新のステータスの固有ID</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        Public Function GetUserTimeline(ByVal maxPage As Integer, ByVal lastStatusID As Long, ByVal userName As String) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetUserTimeline
            Dim statusList As New List(Of TwitterStatus)

            For page As Integer = 1 To maxPage
                Dim options As New NameValueCollection()
                If lastStatusID > 0 Then
                    options.Add("since_id", lastStatusID.ToString())
                End If
                options.Add("page", page.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlStatuses + "/user_timeline/" + userName + ".json"
                Dim res As String = webClient.HttpGet(url, options, _userName, _password)
                statusList.AddRange(Me.CreateTwitterStatuses(res))
            Next

            Return statusList
        End Function

        ''' <summary>
        ''' ユーザーのお気に入りを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatus">取得済みの最新のステータス</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        ''' <remarks></remarks>
        Public Function GetUserFavorites(ByVal maxPage As Integer, ByVal lastStatus As Kirishima16.Net.Twitter.TwitterStatus, ByVal user As Kirishima16.Net.Twitter.TwitterUser) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetUserFavorites
            Return GetUserFavorites(maxPage, lastStatus.StatusID, user.UserName)
        End Function

        ''' <summary>
        ''' ユーザーのお気に入りを取得します。
        ''' </summary>
        ''' <param name="maxPage">取得する最大ページ数</param>
        ''' <param name="lastStatusID">取得済みの最新のステータスの固有ID</param>
        ''' <returns>TwitterStatusのコレクション</returns>
        Public Function GetUserFavorites(ByVal maxPage As Integer, ByVal lastStatusID As Long, ByVal userName As String) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterStatus) Implements Kirishima16.Net.Twitter.ITwitterClient.GetUserFavorites
            Dim statusList As New List(Of TwitterStatus)

            For page As Integer = 1 To maxPage
                Dim options As New NameValueCollection()
                If lastStatusID > 0 Then
                    options.Add("since_id", lastStatusID.ToString())
                End If
                options.Add("page", page.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = _urlFavorites + "/" + userName + ".json"
                Dim res As String = webClient.HttpGet(url, options, _userName, _password)
                statusList.AddRange(Me.CreateTwitterStatuses(res))
            Next

            Return statusList
        End Function


#Region "ids関連(インターフェース外)"
        Private Sub parseIds(ByVal userList As List(Of TwitterUser), ByVal res As String)
            Using resStream As New System.IO.StringReader(res)
                Using reader As Xml.XmlReader = Xml.XmlReader.Create(resStream)
                    While reader.Read()
                        If reader.IsStartElement() AndAlso Not reader.IsEmptyElement AndAlso reader.Name = "id" Then
                            Dim user As New TwitterUser()
                            user.UserID = reader.ReadElementContentAsLong()
                            userList.Add(user)
                        End If
                    End While
                End Using
            End Using
        End Sub

        ''' <summary>
        ''' すべてのページから自分をフォローしているユーザーのコレクションを取得します。
        ''' </summary>
        ''' <returns>ユーザーのコレクション</returns>
        Public Function GetFollowersIds() As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterUser)
            Dim page As Integer = 0
            Dim userList As New List(Of TwitterUser)
            Dim tmpUserList As New List(Of TwitterUser)
            Do
                page = page + 1
                tmpUserList.Clear()
                tmpUserList = DirectCast(GetFollowersIds(page, page), List(Of TwitterUser))
                userList.AddRange(tmpUserList)
            Loop While tmpUserList.Count >= 5000 'idsの取得件数が5000件単位なので、5000件取得したら次のページがあるかも知れないので取りにいく

            Return userList
        End Function

        ''' <summary>
        ''' ページを指定して自分をフォローしているユーザーのコレクションを取得します。
        ''' </summary>
        ''' <param name="beginPage">取得開始ページ</param>
        ''' <param name="endPage">取得終了ページ</param>
        ''' <returns>フォローしているユーザーのコレクション</returns>
        Public Function GetFollowersIds(ByVal beginPage As Integer, ByVal endPage As Integer) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterUser)
            Dim userList As New List(Of TwitterUser)

            For i As Integer = beginPage To endPage
                Dim values As New NameValueCollection()
                values.Add("page", i.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = "http://twitter.com/followers/ids.xml"
                Dim res As String = webClient.HttpGet(url, values, _userName, _password)
                parseIds(userList, res)
            Next

            Return userList
        End Function

        ''' <summary>
        ''' すべてのページから自分がフォローしているユーザーのコレクションを取得します。
        ''' </summary>
        ''' <returns>ユーザーのコレクション</returns>
        Public Function GetFriendsIds() As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterUser)
            Dim page As Integer = 0
            Dim userList As New List(Of TwitterUser)
            Dim tmpUserList As New List(Of TwitterUser)
            Do
                page = page + 1
                tmpUserList.Clear()
                tmpUserList = DirectCast(GetFriendsIds(page, page), List(Of TwitterUser))
                userList.AddRange(tmpUserList)
            Loop While tmpUserList.Count >= 5000 'idsの取得件数が5000件単位なので、5000件取得したら次のページがあるかも知れないので取りにいく

            Return userList
        End Function

        ''' <summary>
        ''' ページを指定して自分がフォローしているユーザーのコレクションを取得します。
        ''' </summary>
        ''' <param name="beginPage">取得開始ページ</param>
        ''' <param name="endPage">取得終了ページ</param>
        ''' <returns>ユーザーのコレクション</returns>
        Public Function GetFriendsIds(ByVal beginPage As Integer, ByVal endPage As Integer) As System.Collections.Generic.IList(Of Kirishima16.Net.Twitter.TwitterUser)
            Dim userList As New List(Of TwitterUser)

            For i As Integer = beginPage To endPage
                Dim values As New NameValueCollection()
                values.Add("page", i.ToString())
                Dim webClient As WebClient = Nothing
                Dim url As String = "http://twitter.com/friends/ids.xml"
                Dim res As String = webClient.HttpGet(url, values, _userName, _password)
                parseIds(userList, res)
            Next

            Return userList
        End Function
#End Region
    End Class
End Namespace